#ifndef ESTRATEGIAALMACENAMIENTO_H_
#define ESTRATEGIAALMACENAMIENTO_H_

#include "Clave.h"
#include "Almacenamiento.h"
#include "Bloque.h"
#include "Registro.h"


namespace Toolkit
{

/**
 * TODO implementar una lista con porcentaje de espacio libre en bloques en que se borraron cosas,
 * y ordenarla de manera, que se implemente una politica de worst fit.
 */

class EstrategiaAlmacenamiento
{
public:
    EstrategiaAlmacenamiento();
    virtual ~EstrategiaAlmacenamiento();

    /**
     * Se almacena el dato indicado en el almacenamiento.
     * Si su serialización excede el tamaño especificado para el almacenamiento, 
     * se arroja una excepción.
     */
    virtual unsigned long int guardarDato (Almacenamiento &almacenamiento, Dato &dato,
                    const Clave &clave, const string &nombreAlmacenamiento) = 0;

    /**
     * Se reemplaza el dato cuya clave se pasa y que se encuentra en la posición dada,
     * por aquel pasado como parámetro. Se devuelve la posición en que se guarda nuevamente 
     * (depende la estrategia, es posible que se haga necesario ubicarlo en una nueva posición
     * dentro del almacenamiento). 
     * Si la serialización del dato excede el tamaño especificado para el almacenamiento, 
     * se arroja una excepción.
     */
    virtual unsigned long int modificarDato (Almacenamiento &almacenamiento, Dato &dato, const Clave &clave,
                    const unsigned long int posicion, const string &nombreAlmacenamiento) = 0;

    /**
     * Se devuelve en el dato pasado aquel cuya clave es la especificada, tras buscarlo en la posición
     * especificada del almacenamiento.
     */
    //TODO no era una lista? por que?
    virtual void recuperarDato (Almacenamiento &almacenamiento, const unsigned long int posicion, Dato &dato,
                    const Clave &clave, const string &nombreAlmacenamiento) = 0;

    /**
     * Se elimina del almacenamiento el dato cuya clave es pasada (que se busca en la posición especificada),
     * y se lo devuelve en el dato pasado.
     */
    virtual void eliminarDato (Almacenamiento &almacenamiento, const long unsigned int posicion,
                    Dato &dato, const Clave &clave, const string &nombreAlmacenamiento) = 0;
                    
protected:
	/**
	 * Devuelve una nueva instancia de registro a partir del nombre de almacenamiento
	 * indicado. La memoria asociada al puntero debe ser eliminada por el que llame al metodo.
	 * */
	Registro* nuevoRegistro(const string &nombreAlmacenamiento) const;
	
	/**
	 * Devuelve una nueva instancia de bloque a partir del nombre de almacenamiento
	 * indicado. La memoria asociada al puntero debe ser eliminada por el que llame al metodo.
	 * */
	Bloque* nuevoBloque(const string &nombreAlmacenamiento) const;


};

}

#endif /* ESTRATEGIAALMACENAMIENTO_H_ */
